package com.boby.homecamera.view

import android.content.Context
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.VelocityTracker
import android.view.View
import android.view.ViewConfiguration
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.OverScroller
import android.widget.TextView
import com.boby.homecamera.R
import com.boby.homecamera.constant.Constant
import com.boby.homecamera.db.VideoTable
import com.boby.homecamera.net.Api
import com.boby.lib_common.extens.dp
import com.boby.lib_common.extens.setCornerRadius
import com.boby.lib_common.util.BLog
import com.bumptech.glide.Glide
import com.bumptech.glide.load.model.GlideUrl
import com.bumptech.glide.load.model.LazyHeaders
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min


class EfficientVerticalListView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : ViewGroup(context, attrs) {
    private val TAG = "VerticalListView"
    private var childCacheSize = 2
    private val data = mutableListOf<VideoTable.Video>()
    private val cacheViews = mutableListOf<View>()
    private var totalHeight = 0

    private var totalScrollY = 0f
     var lastTouchTime = 0L
     var isUserScroll = false
//    private val gestureDetector = GestureDetector(context, this)
    private var scroller = OverScroller(context)
    private var mVelocityTracker: VelocityTracker? = null
    private var MAX_VELOCITY = ViewConfiguration.get(context).scaledMaximumFlingVelocity
    private var MIN_VELOCITY = ViewConfiguration.get(context).scaledMinimumFlingVelocity
    private var scrollListener: ((Float) -> Unit)? = null
    private var itemClickListener: ((index:Int,item:VideoTable.Video)->Unit ?)? = null
     var itemHeight = 100
     var firstItemTop = 0
     var lastItemBottom = 0

    private var ip:String = ""
    private var token:String = ""
    private var httpPort:Int = Constant.HTTP_SERVER_PORT
    fun setIp(ip:String,token:String,httpPort:Int){
        this.ip = ip
        this.token = token
        this.httpPort = httpPort
    }

    fun setItemClickListener(listener: (index:Int,item:VideoTable.Video) -> Unit ){
        this.itemClickListener = listener
    }
    // --------------------- API ---------------------
    fun setData(items: List<VideoTable.Video>) {
        data.clear()
        data.addAll(items)
        childCacheSize = ( height.toFloat()/itemHeight.toFloat() + 4).toInt()
        totalHeight = 0
        for (i in 0 until items.size) {
            totalHeight += itemHeight
        }
        if(totalHeight != 0){
            totalHeight += firstItemTop
//            totalHeight += lastItemBottom
        }

        totalScrollY = 0f
        requestLayout()
    }
    fun getData(): List<VideoTable.Video> {
        return data
    }

    fun setOnScrollListener(listener: (Float) -> Unit) {
        scrollListener = listener
    }
    fun getCenterItemOffset(scrolly: Float):Pair<Int, Float?> {
//        val scrolly = totalScrollY
       val centerItemIndex = (scrolly  / itemHeight).toInt()
       val centerItemOffset = scrolly  % itemHeight
        return Pair(centerItemIndex, centerItemOffset)
    }

    fun scrollToY(offset: Int) {
        isUserScroll = false
//        BLog.d(TAG,"smoothScrollY offset:$offset")
        if(offset < 0 ){
            totalScrollY = 0f
        }else if (offset >= totalHeight){
            totalScrollY = totalHeight.toFloat()
        }else{
            totalScrollY = offset.toFloat()
        }
        post {
            layoutChildren()
        }

    }

    fun smoothScrollY(offset: Int = 0) {
//        BLog.d(TAG,"smoothScrollY offset:$offset")
        if(offset < 0 ){
            totalScrollY = 0f
        }else if (offset >= totalHeight){
            totalScrollY = totalHeight.toFloat()
        }else{
            scroller.startScroll(0, totalScrollY.toInt(), 0, (offset - totalScrollY).toInt(), 500)
        }
    }

    // --------------------- 滑动 ---------------------
    private fun scrollByDy(dy: Float) {
//        BLog.d(TAG,"scrollByDy dy:$dy")
        totalScrollY += dy
        fixScrollBounds()
        post {
            layoutChildren()
        }
        scrollListener?.invoke(totalScrollY)
    }

    private fun fixScrollBounds() {
//        val maxScroll = max(0, itemHeights.sum() - height)
//        totalScrollY = min(max(totalScrollY, 0f), maxScroll.toFloat())
    }

    // --------------------- 布局 & 复用 ---------------------
    private fun layoutChildren() {
        if (data.isEmpty() || height == 0) return

        val firstVisibleIndex = findFirstVisibleIndex()
        val lastVisibleIndex = findLastVisibleIndex(firstVisibleIndex)
//        BLog.d(TAG,"layoutChildren firstVisibleIndex:$firstVisibleIndex, lastVisibleIndex:$lastVisibleIndex ,totalScrollY：$totalScrollY")
        // 回收滑出屏幕的 view
        if(cacheViews.isEmpty()){
            for (i in 0 until childCacheSize) {
                val  view = createItemView()
                addView(view)
                view.layout(0, -itemHeight, width,  0)
                view.setTag(R.id.tag_position,-1)
                cacheViews.add(view)
            }
        }
        val bindPosition = mutableListOf<Int>()
        val recycledViews = mutableListOf<View>()

//        val top = offsetForIndex(firstVisibleIndex)
        val top = totalScrollY.toInt()
        cacheViews.forEachIndexed { index, view ->
            val pos = view.getTag(R.id.tag_position) as Int
            if (pos >= firstVisibleIndex && pos <= lastVisibleIndex) {
                layoutItemView(view, pos,firstVisibleIndex,top)
                bindPosition.add(pos)
            }else{
                recycledViews.add(view)
            }
        }
//        BLog.d(TAG,"layoutChildren bindPosition:$bindPosition recycledViews size:${recycledViews.size}")
        for (i in firstVisibleIndex..lastVisibleIndex) {
            if(i !in bindPosition){
                if(recycledViews.isNotEmpty()){
                    val view = recycledViews.removeAt(0)
                    view.setTag(R.id.tag_position,i)
                    bindView(view, i,data[i])
                    layoutItemView(view, i,firstVisibleIndex,top)
                }
            }
        }
        //不可见view
        for (view in recycledViews) {
            view.setTag(R.id.tag_position,-1)
            view.layout(0, -itemHeight, width,  0)
        }

    }

    private fun layoutItemView(view:View, position: Int,firstVisibleIndex:Int ,top:Int){
        val offsetItemHeight =  (position) * itemHeight + firstItemTop  - top
        view.layout(0,  offsetItemHeight  , width,   offsetItemHeight + itemHeight)
//        BLog.d(TAG,"layoutItemView firstVisibleIndex:$firstVisibleIndex, position:$position, top:$top, offsetItemHeight:$offsetItemHeight ,viewTop:${top + offsetItemHeight},viewBottom:${top + offsetItemHeight + itemHeight}")

    }

    private fun findFirstVisibleIndex(): Int {
       var index = ((totalScrollY - firstItemTop )/itemHeight).toInt() - 1
       if(index <= 0){
          return 0
       }
        return min(index, data.size - 1)
    }

    private fun findLastVisibleIndex(firstVisible: Int): Int {
        val visibleCount = (height.toFloat() / itemHeight) + 2
//        BLog.d(TAG,"findLastVisibleIndex firstVisible:$firstVisible, visibleCount:$visibleCount ,height:$height, itemHeight:$itemHeight")
        return min(data.size - 1, max(0, firstVisible + visibleCount.toInt() ))
    }


    private fun createItemView(): View {
        val view =  LayoutInflater.from(context).inflate(R.layout.item_video,null,false)
            .apply {
            layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
        }
        view.tag = VideoViewHolder(view)
        return view
    }

    private fun bindView(view: View, position:Int,item: VideoTable.Video) {
//        (view as TextView).text = data
        val holder = view.tag
        if(holder != null && holder is VideoViewHolder){
            holder.time_length.text= formatTimemmss((item.endTime!! - item.startTime!!)/1000 )
            holder.time.text= formatTimeHHmmss(item.startTime!!)
            holder.itemView.setOnClickListener {
                isUserScroll = false
                itemClickListener?.invoke(position,item)
            }


            val currentUrl = GlideUrl(
                "${Api.getRealUrl(ip,httpPort)}/video/getpic/?path=${item.path}",
                LazyHeaders.Builder()
                    .addHeader("Authorization", "Bearer ${token}")
                    .build()
            )
            holder.iv_video_preview.tag = currentUrl
            holder.iv_video_preview.setCornerRadius(10f.dp())
            Glide.with(holder.iv_video_preview.context)
                .load(currentUrl)
                .dontAnimate()
                .into(object : CustomTarget<Drawable>() {
                    override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
                        // ✅ 加载完成后再判断是否仍是当前绑定的 item
                        if (holder.iv_video_preview.tag == currentUrl) {
                            holder.iv_video_preview.setImageDrawable(resource)
                        }
                    }

                    override fun onLoadCleared(placeholder: Drawable?) {
                        holder.iv_video_preview.setImageDrawable(placeholder)
                    }
                })
//            .into(holder.iv_video_preview)
        }
    }

    // --------------------- 测量 ---------------------
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

        val widthSize = MeasureSpec.getSize(widthMeasureSpec)
        val heightSize = MeasureSpec.getSize(heightMeasureSpec)
        // 🔒 永远占满父容器的高度
        setMeasuredDimension(widthSize, heightSize)

//        BLog.d(TAG,"onMeasure widthSize:$widthSize, heightSize:$heightSize")
        // 只测量可见 view
        cacheViews.forEach {
            var index = it.getTag(R.id.tag_position) as Int
            if (index == 0) {
                measureChild(
                    it,
                    widthMeasureSpec,
                    MeasureSpec.makeMeasureSpec(itemHeight + firstItemTop, MeasureSpec.EXACTLY)
                )
            } else if (index == data.size - 1) {
                measureChild(
                    it,
                    widthMeasureSpec,
                    MeasureSpec.makeMeasureSpec(itemHeight, MeasureSpec.EXACTLY)
                )
            } else {
                measureChild(
                    it,
                    widthMeasureSpec,
                    MeasureSpec.makeMeasureSpec(itemHeight + lastItemBottom, MeasureSpec.EXACTLY)
                )

            }
        }


    }

    // --------------------- Touch ---------------------

    override fun onLayout(
        changed: Boolean,
        l: Int,
        t: Int,
        r: Int,
        b: Int
    ) {
        layoutChildren()
    }
    private var lastScrollY = 0f
    override fun onTouchEvent(e: MotionEvent): Boolean {

        lastTouchTime = System.currentTimeMillis()
        if(mVelocityTracker == null){
            mVelocityTracker = VelocityTracker.obtain()
        }
        mVelocityTracker?.addMovement(e)
        when (e.action) {
            MotionEvent.ACTION_DOWN -> {
                isUserScroll = true
                if (!scroller.isFinished) {
                    stopComputeScroller()
                    scroller.forceFinished(true);
                }
                startX = e.rawX
                startY = e.rawY
                // 清除旧的滚动状态
                parent.requestDisallowInterceptTouchEvent(false)
                lastScrollY = 0f
//                BLog.d(TAG,"onTouchEvent down  lastScrollY:$lastScrollY")
            }

            MotionEvent.ACTION_MOVE -> {
                val scrollY = e.rawY - startY
                val dx = abs(e.rawX - startX)
                val dy = abs(scrollY)
                // 如果竖向滑动大于横向滑动，则拦截事件，交给 RecyclerView 处理
//                if (dy > dx && dy > touchSlop) {
                if (dy > dx ) {
                    parent.requestDisallowInterceptTouchEvent(true)
                }
//                BLog.d(TAG,"scroll 1 lastScrollY:$lastScrollY, scrollY:$scrollY")
                scrollByDy(lastScrollY - scrollY )

                lastScrollY = scrollY
            }

            MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> {
                // 重置拦截状态
                parent.requestDisallowInterceptTouchEvent(false)
                val scrollY = e.rawY - startY
                scrollByDy(lastScrollY - scrollY )
                lastScrollY = scrollY

                mVelocityTracker!!.computeCurrentVelocity(500, MAX_VELOCITY.toFloat())
                val yVelocity = mVelocityTracker!!.yVelocity.toInt()
//                BLog.d(TAG, "yVelocity:$yVelocity MIN_VELOCITY:$MIN_VELOCITY totalScrollY:$totalScrollY totalHeight:$totalHeight")
                if (abs(yVelocity) >= MIN_VELOCITY) {
                    scroller.fling(0, totalScrollY.toInt(), 0, -yVelocity, 0, 0, 0, totalHeight - (height/2f).toInt())
                    startComputeScroller(0)
                } else {
                     if(totalScrollY > totalHeight - height/2f){
                         totalScrollY = totalHeight - height/2f
                         isUserScroll = false
                         post {
                             layoutChildren()
                         }
                         scrollListener?.invoke(totalScrollY)
                    }else if(totalScrollY < 0){
                         totalScrollY = 0f
                         isUserScroll = false
                         post {
                             layoutChildren()
                         }
                         scrollListener?.invoke(totalScrollY)
                    }
                }
                mVelocityTracker?.recycle()
                mVelocityTracker = null
            }
        }
//        gestureDetector.onTouchEvent(e)
        return true
    }

    override fun computeScroll() {

    }
    private var computeScrollerRunnable = Runnable {
        myComputeScroll()
    }

    private fun startComputeScroller(delay:Long){
        removeCallbacks(computeScrollerRunnable)
        if(delay > 0){
            postDelayed(computeScrollerRunnable,delay)
        }else{
            post(computeScrollerRunnable)
        }
    }
    private fun stopComputeScroller(){
        removeCallbacks(computeScrollerRunnable)
    }

    private fun myComputeScroll(){
        val scrollY = scroller.currY.toFloat()
        if (scroller.computeScrollOffset()) {
            if(scroller.isFinished ){
                isUserScroll = false
            }
            totalScrollY = scrollY
            fixScrollBounds()
            layoutChildren()
            scrollListener?.invoke(totalScrollY)
            startComputeScroller(10)
        }else{
            isUserScroll = false
        }

    }

    private var startX = 0f
    private var startY = 0f
    private var startX2 = 0f
    private var startY2 = 0f
    private val touchSlop = ViewConfiguration.get(context).scaledTouchSlop
//    override fun onInterceptTouchEvent(e: MotionEvent) = true
    override fun onInterceptTouchEvent(e: MotionEvent): Boolean {
        when (e.action) {
            MotionEvent.ACTION_DOWN -> {
                startX2 = e.x
                startY2 = e.y
                onTouchEvent(e)
            }
            MotionEvent.ACTION_MOVE -> {
                val dx = abs(e.x - startX2)
                val dy = abs(e.y - startY2)
                // 竖直滑动距离大于阈值时，才拦截，自己处理滚动
                if (dy > dx && dy > touchSlop) {
                    onTouchEvent(e)
                    return true
                }
            }
        }
        return false  // 默认不拦截，保证子 view 能收到点击事件
    }


    public class VideoViewHolder(val itemView:View){
        val time_length = itemView.findViewById<TextView>(R.id.time_length)
        val time = itemView.findViewById<TextView>(R.id.time)
        val iv_video_preview = itemView.findViewById<ImageView>(R.id.iv_video_preview)
    }

    fun formatTimeHHmmss(timestampMillis: Long): String {
        val sdf: SimpleDateFormat = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
        val date: Date = Date(timestampMillis)
        return sdf.format(date)
    }
    fun formatTimemmss(timeValue: Long): String {
//        val hour = timeValue / 3600
        val minute = (timeValue % 3600) / 60
        val second = timeValue % 60
        return String.format("%02d'%02d", minute, second)
    }
}
